package com.libc.yygh.common;

import cn.hutool.core.map.MapUtil;
import com.libc.yygh.common.bean.BeanHelper;
import com.libc.yygh.common.bean.BeanUtil;
import com.libc.yygh.common.bean.ReflectionUtil;
import com.libc.yygh.common.constant.IPubCons;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 集合对象的一些助手工具类
 *
 * @version 1.0<br>
 * @qualiFild nc.pub.itf.tools.pub.CollectionUtil.java<br>
 * @author：licheng<br>
 * @date Created on 2019-8-12<br>
 */
public final class CollectionUtil implements IPubCons, Cloneable
{
    /************************************************************* <br>
     *
     *说明: Collection 反转<br>
     *
     * @Description   <br>
     * @Date Created on 2022/8/18  16:25  <br>
     * @param c <br>
     * @return java.util.Collection  <br>
     * @Author LIBENCHENG
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static Collection reverse(Collection c)
    {
        if (PubEnvUtil.isEmptyObj(c)) { return null; }
        Collection temp = ReflectionUtil.newInstance(c.getClass());
        Stack stack = new Stack();
        for (Object obj : c) { stack.push(obj); }
        while (!stack.isEmpty()) { temp.add(stack.pop()); }

        return temp;
    }

    /************************************************************* <br>
     *
     *说明: 分组得到想要的数据 <br>
     *
     * @Description   <br>
     * @Date Created on 2022/6/13  12:41  <br>
     * @param dataList
     * @return java.util.Map<String, Map < String, String>>  <br>
     * @Author LIBENCHENG
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static Map< String,Object > receiveGroupMap(List< Map< String,Object > > dataList, Object key, Class zlass)
    {
        return new ConcurrentHashMap< String,Object >()
        {{
            for (Object temp : dataList)
            {
                if (PubEnvUtil.isNotEmptyObj(zlass))
                {
                    temp = BeanUtil.parseVO(temp, zlass);
                    put(StringUtil.valueOfZero(BeanHelper.getProperty(temp, StringUtil.valueOf(key))), temp);
                }
                else if (temp instanceof Map)
                { put(StringUtil.valueOfZero(((Map) temp).get(StringUtil.toString(key))), temp); }
                else
                { throw new RuntimeException("没有达到分组信息！"); }
            }
        }};
    }

    /************************************************************* <br>
     *
     *说明: 分组得到想要的数据<br>
     *
     * @Description   <br>
     * @Date Created on 2022/6/16  18:02  <br>
     * @param dataList
     * @param key 以谁分组<br>
     * @return java.util.Map<java.lang.String, java.util.List < java.util.Map < java.lang.String, java.lang.String>>>
     *     <br>
     * @Author LIBENCHENG
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static Map< String,List > receiveGroupListMap(List< Map< String,Object > > dataList, Object key, Class zlass)
    {
        return new ConcurrentHashMap< String,List >()
        {
            {
                for (Map temp : dataList)
                {
                    Object obj = temp.get(StringUtil.toString(key));
                    if (PubEnvUtil.isNotEmptyObj(zlass))
                    { obj = BeanUtil.parseVO(temp, zlass); }
                    List< Object > tempList = get(temp.get(StringUtil.toString(key)));
                    if (PubEnvUtil.getSize(tempList) < 1)
                    { tempList = new LinkedList< Object >(); }
                    tempList.add(obj);
                    put(StringUtil.valueOfZero(temp.get(StringUtil.toString(key))), tempList);
                }
            }
        };

    }

    /************************************************************* <br>
     *
     *说明: 对象深度克隆<br>
     *
     * @Description   <br>
     * @Date Created on 2022/5/10  16:13  <br>
     * @param obj <br>
     * @return java.lang.Object  <br>
     * @Author LIBENCHENG
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static Object cloneObj(Object obj)
    {
        try
        {

            if (obj instanceof Map)
            {
                Map temMap = (Map) obj;
                HashMap< Object,Object > map = MapUtil.newHashMap();
                temMap.keySet().forEach(key -> map.put(key, temMap.get(key)));

                return map;
            }
            // if (obj instanceof List)
            // {
            //
            //     List tempList = (List) obj;
            //     List idcards = tempList.stream().map(Object :: Obj).collect(Collectors.toList());
            //
            // }
        }
        catch (Exception e)
        {
            return null;
        }

        return deepCloneObj(obj);
    }

    /************************************************************* <br>
     *
     *说明: 对象深度克隆<br>
     *
     * @Description   <br>
     * @Date Created on 2022/5/10  16:13  <br>
     * @param obj <br>
     * @return java.lang.Object  <br>
     * @Author LIBENCHENG
     * @version 1.0 <br>
     ************************************************************* <br>
     */
    public static Object deepCloneObj(Object obj)
    {
        try
        {
            // 将对象写到流⾥
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            ObjectOutputStream oo = new ObjectOutputStream(bo);
            // 从流⾥读出来
            oo.writeObject(obj);
            ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
            ObjectInputStream oi = new ObjectInputStream(bi);
            return (oi.readObject());
        }
        catch (Exception e)
        {
            System.err.println(StringUtil.toString(e));
            return new Object();
        }
    }

    public static String transObj2Josn(Object obj) throws Exception
    {
        if (obj instanceof Map) { return map2Josn((Map) obj); }
        else if (obj instanceof Collection) { return map2Josn((Collection) obj); }
        else if (BeanHelper.isBeanClass(obj.getClass())) { return map2Josn((List) obj); }
        else { throw new IllegalArgumentException("不支持转换成json，请检查确认！"); }
    }

    /**
     * *********************************************************** <br>
     * 说明：mapList转json 内部类，建议使用这个方法<br>
     *
     * @param mapList
     * @return <br>
     * @throws Exception
     * @String <br>
     * @methods pers.bc.utils.pub.CollectionUtil#map2JosnStr <br>
     * @author LiBencheng <br>
     * @date Created on 2020-6-30 <br>
     * @time 上午9:00:06 <br>
     * @version 1.0 <br>
     * ************************************************************ <br>
     * @see <br>
     */
    public static String map2Josn(Collection< ? > mapList) throws Exception
    {
        if (PubEnvUtil.getSize(mapList) < 1) { return EMPTY; }
        StringBuffer strb = new StringBuffer(LEFT_SQ_BRACKET);
        for (Object obj : mapList)
        {
            if (PubEnvUtil.isEmptyObj(obj))
            { strb.append(obj).append(COMMA).append(CRLF); }
            else
            {
                // obj = CollectionUtil.transBean2Map(obj);
                if (obj instanceof Map)
                { strb.append(map2Josn((Map< ?,? >) obj)).append(COMMA).append(CRLF); }
                else if (BeanHelper.isBeanClass(obj.getClass()))
                { strb.append(map2Josn(transBean2Map(obj))).append(COMMA).append(CRLF); }
                else
                { strb.append(obj).append(COMMA).append(CRLF); }
            }
        }

        return deleteStr(strb, 3).append(RIGHT_SQ_BRACKET).toString();
    }

    /**
     * *********************************************************** <br>
     * 说明： map转json,内部类，建议使用这个方法<br>
     *
     * @param map
     * @return <br>
     * @throws Exception
     * @String <br>
     * @methods pers.bc.utils.pub.CollectionUtil#map2JosnStr <br>
     * @author LiBencheng <br>
     * @date Created on 2020-6-30 <br>
     * @time 上午8:59:56 <br>
     * @version 1.0 <br>
     * ************************************************************ <br>
     * @see <br>
     */
    public static String map2Josn(Map< ?,? > map) throws Exception
    {

        if (PubEnvUtil.getSize(map) < 1) { return EMPTY; }
        StringBuffer sb = new StringBuffer(LEFT_BRACE);
        for (Object key : map.keySet())
        {
            Object obj = map.get(key);
            if (PubEnvUtil.isEmptyObj(obj))
            { appendSubStr(sb, key, obj, Boolean.TRUE); }
            else
            {
                if (obj instanceof Map)
                { appendSubStr(sb, key, map2Josn((Map< ?,? >) obj), Boolean.FALSE); }
                else if (obj instanceof List)
                { appendSubStr(sb, key, map2Josn((List< ? >) obj), Boolean.FALSE); }
                else if (BeanHelper.isBeanClass(obj.getClass()))
                { appendSubStr(sb, key, map2Josn(transBean2Map(obj)), Boolean.FALSE); }
                else if (String.valueOf(obj).contains(LEFT_BRACE) || String.valueOf(obj).contains(LEFT_SQ_BRACKET))
                { appendSubStr(sb, key, obj, Boolean.FALSE); }
                else
                { appendSubStr(sb, key, obj, Boolean.TRUE); }
            }
        }

        return deleteStr(sb, 3).append(RIGHT_BRACE).toString();
    }

    public static Map< String,Object > transBean2Map(Object obj) throws Exception
    {
        if (null == obj) { return null; }
        Map< String,Object > map = new LinkedHashMap< String,Object >();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors)
        {
            String key = property.getName();
            // 过滤class属性
            if (!(key.equals("class") || key.equals("Class")))
            {
                Method getter = property.getReadMethod();
                if (null != getter)
                {
                    Object value = getter.invoke(obj);
                    map.put(key, value);
                }
            }
        }
        return map;
    }

    public static StringBuffer deleteStr(StringBuffer sbStr, int i)
    { return sbStr.delete(sbStr.length() - i, sbStr.length()); }

    public static void appendSubStr(StringBuffer sbStr, Object key, Object objValue, Boolean isAddQuote)
    {
        if (isAddQuote)
        {
            sbStr.append(QUOTE).append(key).append(QUOTE).append(COLON)
                 .append(QUOTE).append(StringUtil.valueOfEmpty(objValue))
                 .append(QUOTE).append(COMMA).append(CRLF);
        }
        else
        {
            sbStr.append(QUOTE).append(key).append(QUOTE).append(COLON)
                 .append(StringUtil.valueOfEmpty(objValue))
                 .append(COMMA).append(CRLF);
        }
    }
}
